#include "service/tracker/StorageChargePriceTracker.h"

#include "core/Logger.h"

#include <ctime>
#include <sstream>

namespace ems {
namespace service {
namespace tracker {

StorageChargePriceTracker::StorageChargePriceTracker() {
    LOG_INFO("StorageChargePriceTracker initialized with default config: "
             << "battery=" << batteryCapacityKwh_ << "kWh, "
             << "day=" << period_.dayStartHour << "-" << period_.dayEndHour << "h, "
             << "maxDelta=" << maxSocDelta_ << "%");
}

void StorageChargePriceTracker::setBatteryCapacity(double capacityKwh) {
    std::lock_guard<std::mutex> lock(mutex_);
    if (capacityKwh > 0.0) {
        batteryCapacityKwh_ = capacityKwh;
        LOG_INFO("StorageChargePriceTracker battery capacity set to " << capacityKwh << " kWh");
    } else {
        LOG_WARN("Invalid battery capacity: " << capacityKwh << ", ignored");
    }
}

void StorageChargePriceTracker::setDayNightPeriod(int dayStartHour, int dayEndHour) {
    std::lock_guard<std::mutex> lock(mutex_);
    if (dayStartHour >= 0 && dayStartHour < 24 && dayEndHour > dayStartHour && dayEndHour <= 24) {
        period_.dayStartHour = dayStartHour;
        period_.dayEndHour = dayEndHour;
        LOG_INFO("StorageChargePriceTracker day period set to " 
                 << dayStartHour << "-" << dayEndHour << "h");
    } else {
        LOG_WARN("Invalid day/night period: " << dayStartHour << "-" << dayEndHour << ", ignored");
    }
}

void StorageChargePriceTracker::setMaxSocDelta(double maxDelta) {
    std::lock_guard<std::mutex> lock(mutex_);
    if (maxDelta > 0.0) {
        maxSocDelta_ = maxDelta;
        LOG_INFO("StorageChargePriceTracker max SOC delta set to " << maxDelta << "%");
    } else {
        LOG_WARN("Invalid max SOC delta: " << maxDelta << ", ignored");
    }
}

void StorageChargePriceTracker::setStorageCostRate(double costRate) {
    std::lock_guard<std::mutex> lock(mutex_);
    if (costRate >= 0.0) {
        storageCostRate_ = costRate;
        LOG_INFO("StorageChargePriceTracker storage cost rate set to " << costRate << " CNY/kWh");
    } else {
        LOG_WARN("Invalid storage cost rate: " << costRate << ", ignored");
    }
}

void StorageChargePriceTracker::onSample(double soc, std::int64_t timestamp, 
                                         double pvPrice, double gridPrice) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 边界检查：SOC 范围
    if (soc < 0.0 || soc > 100.0) {
        LOG_WARN("StorageChargePriceTracker: invalid SOC " << soc << "%, ignored");
        return;
    }
    
    // 时间戳有效性检查
    if (timestamp <= 0) {
        LOG_WARN("StorageChargePriceTracker: invalid timestamp " << timestamp << ", ignored");
        return;
    }
    
    // 首次采样：初始化状态
    if (lastSoc_ < 0.0) {
        lastSoc_ = soc;
        lastTimestamp_ = timestamp;
        LOG_DEBUG("StorageChargePriceTracker: first sample, SOC=" << soc << "%");
        return;
    }
    
    // 时间戳倒退检查
    if (timestamp < lastTimestamp_) {
        LOG_WARN("StorageChargePriceTracker: timestamp rollback detected ("
                 << lastTimestamp_ << " -> " << timestamp << "), ignored");
        return;
    }
    
    // 计算 SOC 增量
    const double deltaSoc = soc - lastSoc_;
    
    // 仅处理充电情况（SOC 增加）
    if (deltaSoc <= 0.0) {
        // SOC 下降或不变，更新状态但不累计
        lastSoc_ = soc;
        lastTimestamp_ = timestamp;
        return;
    }
    
    // 验证增量是否合理（防止跳变）
    if (!isValidDelta(deltaSoc)) {
        LOG_WARN("StorageChargePriceTracker: SOC delta too large (" 
                 << deltaSoc << "% > " << maxSocDelta_ << "%), ignored as jump");
        lastSoc_ = soc;  // 更新为当前值，避免下次继续累积
        lastTimestamp_ = timestamp;
        return;
    }
    
    // 转换为电量（kWh）
    const double deltaEnergy = deltaSoc * batteryCapacityKwh_ / 100.0;
    
    // 判断时段并计算成本
    const bool isDay = isDaytime(timestamp);
    double deltaCost = 0.0;
    
    if (isDay) {
        // 日间光伏充电：光伏发电本身无成本，仅计算储能损耗成本
        deltaCost = deltaEnergy * storageCostRate_;
    } else {
        // 夜间市电充电：按市电价格计算
        deltaCost = deltaEnergy * gridPrice;
    }
    
    // 累计到对应时段
    if (isDay) {
        stats_.dayChargeEnergy += deltaEnergy;
        stats_.dayChargeCost += deltaCost;
        LOG_DEBUG("StorageChargePriceTracker: day charge +" 
                  << deltaEnergy << "kWh @ storage_cost=" << storageCostRate_ 
                  << " CNY/kWh = +" << deltaCost << " CNY");
    } else {
        stats_.nightChargeEnergy += deltaEnergy;
        stats_.nightChargeCost += deltaCost;
        LOG_DEBUG("StorageChargePriceTracker: night charge +" 
                  << deltaEnergy << "kWh @ grid_price=" << gridPrice 
                  << " CNY/kWh = +" << deltaCost << " CNY");
    }
    
    // 更新状态
    lastSoc_ = soc;
    lastTimestamp_ = timestamp;
}

ChargePriceStats StorageChargePriceTracker::getStats() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return stats_;
}

double StorageChargePriceTracker::getDayAveragePrice() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return stats_.getDayAveragePrice();
}

double StorageChargePriceTracker::getNightAveragePrice() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return stats_.getNightAveragePrice();
}

double StorageChargePriceTracker::getTotalAveragePrice() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return stats_.getTotalAveragePrice();
}

void StorageChargePriceTracker::reset() {
    std::lock_guard<std::mutex> lock(mutex_);
    stats_ = ChargePriceStats{};
    lastSoc_ = -1.0;
    lastTimestamp_ = 0;
    LOG_INFO("StorageChargePriceTracker statistics reset");
}

double StorageChargePriceTracker::getLastSoc() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return lastSoc_;
}

std::int64_t StorageChargePriceTracker::getLastTimestamp() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return lastTimestamp_;
}

bool StorageChargePriceTracker::isDaytime(std::int64_t timestamp) const {
    // 转换为本地时间
    std::time_t tt = static_cast<std::time_t>(timestamp);
    std::tm localTime;
    
#ifdef _WIN32
    localtime_s(&localTime, &tt);
#else
    localtime_r(&tt, &localTime);
#endif
    
    const int hour = localTime.tm_hour;
    return hour >= period_.dayStartHour && hour < period_.dayEndHour;
}

bool StorageChargePriceTracker::isValidDelta(double deltaSoc) const {
    return deltaSoc > 0.0 && deltaSoc <= maxSocDelta_;
}

}  // namespace tracker
}  // namespace service
}  // namespace ems
